// src/pages/UserAsset/UserAsset.jsx

import React, { useEffect, useLayoutEffect, useRef, useState, useMemo } from 'react';
import {
  Table,
  Button,
  Modal,
  Form,
  InputNumber,
  DatePicker,
  Input,
  Select,
  message,
  Spin,
  Card,
  Typography,
} from 'antd';
import * as echarts from 'echarts';
import { useNavigate } from 'react-router-dom';
import {
  $addUserAsset,
  $getUserAssets,
  $deleteUserAsset,
} from '../../api/userAssetApi';
import { $fetchStockList } from '../../api/stockApi';
import { $fetchFundList } from '../../api/fundApi';
import { $fetchBondList } from '../../api/bondApi';
import { $fetchSpotForexList } from '../../api/forexApi';
import './UserAsset.scss';

const { Option } = Select;
const { Text } = Typography;

/** 从 localStorage 获取用户 ID */
const getUserId = () => {
  const userInfo = localStorage.getItem('user_info');
  if (!userInfo) throw { msg: '用户未登录或未找到用户信息' };
  try {
    return JSON.parse(userInfo).id;
  } catch {
    throw { msg: '用户信息解析失败' };
  }
};

const UserAsset = ({ userid }) => {
  // — 1. 用户原始资产列表
  const [assets, setAssets] = useState([]);
  // — 2. 加载态
  const [loading, setLoading] = useState(true);
  // — 3. “手动添加资产”弹窗
  const [isModalOpen, setIsModalOpen] = useState(false);

  // — 4. 各品类最新价/净值映射
  const [stockPriceMap, setStockPriceMap] = useState({});
  const [fundNetMap, setFundNetMap] = useState({});
  const [bondPriceMap, setBondPriceMap] = useState({});
  const [forexPriceMap, setForexPriceMap] = useState({});

  // — 5. 路由跳转
  const navigate = useNavigate();

  // — 6. ECharts 引用 & 实例
  const pieAllRef = useRef(null);
  const pieAllChart = useRef(null);
  const pieStockRef = useRef(null);
  const pieStockChart = useRef(null);
  const barRef = useRef(null);
  const barChart = useRef(null);

  // ─────────────────────────────────────────────────────────────
  // Step1：挂载后拉取用户资产列表
  useEffect(() => {
    const fetchAssets = async () => {
      setLoading(true);
      try {
        const res = await $getUserAssets(userid);
        setAssets(res.data || []);
      } catch (err) {
        console.error('[UserAsset] 获取资产失败：', err);
        message.error(err.msg || '获取资产列表失败');
      } finally {
        setLoading(false);
      }
    };
    fetchAssets();
  }, [userid]);

  // ─────────────────────────────────────────────────────────────
  // Step2：当 assets 更新后，批量并行拉取各品类最新价/净值
  useEffect(() => {
    if (!assets.length) {
      setStockPriceMap({});
      setFundNetMap({});
      setBondPriceMap({});
      setForexPriceMap({});
      return;
    }

    // 提取各品类代码
    const stockSymbols = assets
      .filter((item) => item.type === '股票')
      .map((item) => item.products_id);
    const fundCodes = assets
      .filter((item) => item.type === '基金')
      .map((item) => item.products_id);
    const bondSymbols = assets
      .filter((item) => item.type === '债券')
      .map((item) => item.products_id);
    const forexCodes = assets
      .filter((item) => item.type === '外汇')
      .map((item) => item.products_id);

    const tasks = [];

    // —— 股票行情
    if (stockSymbols.length) {
      tasks.push(
        $fetchStockList()
          .then((list) => {
            const map = {};
            const symSet = new Set(stockSymbols);
            list.forEach((it) => {
              if (symSet.has(it.symbol)) {
                map[it.symbol] = parseFloat(it.price);
              }
            });
            setStockPriceMap(map);
          })
          .catch((_) => {
            message.error('获取股票实时价格失败');
            setStockPriceMap({});
          })
      );
    } else {
      setStockPriceMap({});
    }

    // —— 基金净值
    if (fundCodes.length) {
      tasks.push(
        $fetchFundList()
          .then((list) => {
            const map = {};
            const fSet = new Set(fundCodes);
            list.forEach((it) => {
              if (fSet.has(it.code)) {
                map[it.code] = parseFloat(it.unit_net_value);
              }
            });
            setFundNetMap(map);
          })
          .catch((_) => {
            message.error('获取基金最新单位净值失败');
            setFundNetMap({});
          })
      );
    } else {
      setFundNetMap({});
    }

    // —— 债券价格
    if (bondSymbols.length) {
      tasks.push(
        $fetchBondList()
          .then((list) => {
            const map = {};
            const bSet = new Set(bondSymbols);
            list.forEach((it) => {
              if (bSet.has(it.symbol)) {
                map[it.symbol] = parseFloat(it.trade);
              }
            });
            setBondPriceMap(map);
          })
          .catch((_) => {
            message.error('获取债券最新价格失败');
            setBondPriceMap({});
          })
      );
    } else {
      setBondPriceMap({});
    }

    // —— 外汇现价
    if (forexCodes.length) {
      tasks.push(
        $fetchSpotForexList()
          .then((list) => {
            const map = {};
            const fxSet = new Set(forexCodes);
            list.forEach((it) => {
              if (fxSet.has(it.code)) {
                map[it.code] = parseFloat(it.latest_price);
              }
            });
            setForexPriceMap(map);
          })
          .catch((_) => {
            message.error('获取外汇最新价格失败');
            setForexPriceMap({});
          })
      );
    } else {
      setForexPriceMap({});
    }

    // 并行执行所有请求
    Promise.all(tasks).catch((err) => console.error(err));
  }, [assets]);

  // ─────────────────────────────────────────────────────────────
  // Step3：使用 useMemo 计算“成本市值、当前市值、盈亏(¥)、盈亏(%)”
  const computedAssets = useMemo(() => {
    if (!assets.length) return [];

    return assets.map((item) => {
      const qty = Number(item.quantity);
      const cost = Number(item.buy_price);
      let curPrice = null;

      switch (item.type) {
        case '股票':
          curPrice = Number(stockPriceMap[item.products_id] ?? null);
          break;
        case '基金':
          curPrice = Number(fundNetMap[item.products_id] ?? null);
          break;
        case '债券':
          curPrice = Number(bondPriceMap[item.products_id] ?? null);
          break;
        case '外汇':
          curPrice = Number(forexPriceMap[item.products_id] ?? null);
          break;
        default:
          break;
      }

      const costValue = cost * qty; // 成本市值
      const marketValue =
        curPrice != null && !isNaN(curPrice) ? curPrice * qty : null; // 当前市值
      const profitLoss =
        curPrice != null && !isNaN(curPrice)
          ? (curPrice - cost) * qty
          : null; // 盈亏(绝对值)
      const profitPct =
        profitLoss != null && costValue > 0
          ? (profitLoss / costValue) * 100
          : null; // 盈亏(%)

      return {
        ...item,
        currentPrice: curPrice,
        costValue,
        marketValue,
        profitLoss,
        profitPct,
      };
    });
  }, [assets, stockPriceMap, fundNetMap, bondPriceMap, forexPriceMap]);

  // ─────────────────────────────────────────────────────────────
  // Step4：定义一个通用的饼图初始化函数
  const initPieChart = (rootRef, chartRef, title, rawData, emptyLabel) => {
    if (!rootRef.current) return;
    const chart = chartRef.current || echarts.init(rootRef.current);
    chartRef.current = chart;

    // “无数据”场景
    if (!rawData.length) {
      chart.setOption({
        title: {
          text: title,
          left: 'center',
          textStyle: { fontSize: 16 },
        },
        tooltip: {
          trigger: 'item',
          formatter: () => `${emptyLabel}: 100%`,
        },
        series: [
          {
            name: title,
            type: 'pie',
            radius: '55%',
            center: ['50%', '55%'],
            data: [{ value: 1, name: emptyLabel }],
            label: {
              formatter: '{b}: {d}%',
            },
          },
        ],
      });
      chart.resize();
      return;
    }

    // “有数据”场景：计算总和与百分比
    const totalValue = rawData.reduce((sum, it) => sum + it.value, 0);
    if (totalValue <= 0) {
      chart.setOption({
        title: {
          text: title,
          left: 'center',
          textStyle: { fontSize: 16 },
        },
        tooltip: {
          trigger: 'item',
          formatter: () => `${emptyLabel}: 100%`,
        },
        series: [
          {
            name: title,
            type: 'pie',
            radius: '55%',
            center: ['50%', '55%'],
            data: [{ value: 1, name: emptyLabel }],
            label: {
              formatter: '{b}: {d}%',
            },
          },
        ],
      });
      chart.resize();
      return;
    }

    const pieData = rawData.map((it) => ({
      name: it.name,
      value: Number(it.value.toFixed(2)),
      percent: Number(((it.value / totalValue) * 100).toFixed(2)),
    }));

    chart.setOption({
      title: {
        text: title,
        left: 'center',
        textStyle: { fontSize: 16 },
      },
      tooltip: {
        trigger: 'item',
        formatter: (params) => {
          const { name, value, percent } = params.data;
          return `${name}<br/>市值：¥${value.toLocaleString()}<br/>占比：${percent}%`;
        },
      },
      legend: {
        orient: 'vertical',
        left: 10,
        data: pieData.map((i) => i.name),
        top: 50,
      },
      series: [
        {
          name: title,
          type: 'pie',
          radius: '55%',
          center: ['50%', '55%'],
          data: pieData.map((i) => ({
            name: i.name,
            value: i.value,
            percent: i.percent,
          })),
          emphasis: {
            itemStyle: {
              shadowBlur: 10,
              shadowOffsetX: 0,
              shadowColor: 'rgba(0, 0, 0, 0.5)',
            },
          },
          label: {
            formatter: '{b}: {d}%',
          },
        },
      ],
    });
    chart.resize();
  };

  // ─────────────────────────────────────────────────────────────
  // Step5：初始化/更新“所有资产市值占比”饼图
  useLayoutEffect(() => {
    // 先构建“按类型合并市值”的原始数据
    const typeMap = { 股票: 0, 基金: 0, 债券: 0, 外汇: 0 };
    computedAssets.forEach((it) => {
      if (it.marketValue != null && !isNaN(it.marketValue)) {
        typeMap[it.type] += it.marketValue;
      }
    });
    const rawData = Object.entries(typeMap)
      .filter(([, v]) => v > 0)
      .map(([name, value]) => ({ name, value }));

    initPieChart(
      pieAllRef,
      pieAllChart,
      '所有资产市值占比',
      rawData,
      '无资产'
    );
  }, [computedAssets]);

  // ─────────────────────────────────────────────────────────────
  // Step6：初始化/更新“股票持仓市值占比”饼图
  useLayoutEffect(() => {
    const rawData = computedAssets
      .filter((it) => it.type === '股票' && it.marketValue != null && !isNaN(it.marketValue))
      .map((it) => ({ name: it.products_id, value: it.marketValue }));

    initPieChart(
      pieStockRef,
      pieStockChart,
      '股票持仓市值占比',
      rawData,
      '无股票'
    );
  }, [computedAssets]);

  // ─────────────────────────────────────────────────────────────
  // Step7：初始化/更新“股票持仓盈亏 (¥)”条形图
  useLayoutEffect(() => {
    if (!barRef.current) return;
    const rawData = computedAssets
      .filter(
        (it) =>
          it.type === '股票' &&
          it.profitLoss != null &&
          !isNaN(it.profitLoss)
      )
      .map((it) => ({ name: it.products_id, value: Number(it.profitLoss) }));

    const chart = barChart.current || echarts.init(barRef.current);
    barChart.current = chart;

    // “无股票”场景
    if (!rawData.length) {
      chart.setOption({
        title: {
          text: '股票持仓盈亏 (¥)',
          left: 'center',
          textStyle: { fontSize: 16 },
        },
        grid: {
          left: '5%',
          right: '5%',
          bottom: '15%',
          containLabel: true,
        },
        xAxis: {
          type: 'category',
          data: ['无股票'],
          axisLabel: { fontSize: 12 },
        },
        yAxis: {
          type: 'value',
          name: '盈亏 (¥)',
          axisLabel: { formatter: '{value}' },
        },
        series: [
          {
            name: '盈亏',
            type: 'bar',
            data: [0],
            itemStyle: {
              color: '#B0BEC5',
            },
          },
        ],
        tooltip: {
          trigger: 'item',
          formatter: () => '当前无股票',
        },
      });
      chart.resize();
      return;
    }

    // “有数据”场景
    chart.setOption({
      title: {
        text: '股票持仓盈亏 (¥)',
        left: 'center',
        textStyle: { fontSize: 16 },
      },
      tooltip: {
        trigger: 'item',
        formatter: (params) => {
          const val = Number(params.value).toFixed(2);
          return `股票 ${params.name}<br/>盈亏：¥${val}`;
        },
      },
      xAxis: {
        type: 'category',
        data: rawData.map((i) => i.name),
        axisLabel: { rotate: 30, fontSize: 12 },
      },
      yAxis: {
        type: 'value',
        name: '盈亏 (¥)',
        axisLabel: { formatter: '{value}' },
      },
      grid: {
        left: '5%',
        right: '5%',
        bottom: '15%',
        containLabel: true,
      },
      series: [
        {
          name: '盈亏',
          type: 'bar',
          data: rawData.map((i) => i.value),
          itemStyle: {
            // 正数绿，负数红
            color: (params) => (params.value >= 0 ? '#52c41a' : '#f5222d'),
          },
        },
      ],
    });
    chart.resize();
  }, [computedAssets]);

  // ─────────────────────────────────────────────────────────────
  // Step8：组件卸载时销毁所有 ECharts 实例，避免内存泄漏
  useEffect(() => {
    return () => {
      pieAllChart.current && pieAllChart.current.dispose();
      pieStockChart.current && pieStockChart.current.dispose();
      barChart.current && barChart.current.dispose();
    };
  }, []);

  // ─────────────────────────────────────────────────────────────
  // 删除资产
  const handleDeleteAsset = async (assetId) => {
    try {
      await $deleteUserAsset(assetId);
      message.success('资产删除成功');
      setAssets((prev) => prev.filter((a) => a.id !== assetId));
    } catch (err) {
      console.error(err);
      message.error(err.msg || '删除资产失败');
    }
  };

  // 添加资产
  const handleAddAsset = async (values) => {
    try {
      const userIdLocal = getUserId();
      if (!userIdLocal) {
        message.error('用户未登录，请先登录');
        return;
      }
      const { products_id, products_name, type, quantity, buy_price, buy_time } =
        values;
      const formattedTime = buy_time.format('YYYY-MM-DD HH:mm:ss');
      const res = await $addUserAsset({
        userid: userIdLocal,
        products_id,
        products_name,
        type,
        quantity,
        buy_price,
        buy_time: formattedTime,
      });
      message.success('资产添加成功');
      setIsModalOpen(false);

      // 直接把新增项追加到本地状态，避免再次全量拉取
      const newAsset = {
        id: res.data?.id || Date.now(), // 如果接口返回了 id 就用，否则用临时时间戳
        products_id,
        products_name,
        type,
        quantity,
        buy_price,
        buy_time: formattedTime,
      };
      setAssets((prev) => [...prev, newAsset]);
    } catch (err) {
      console.error(err);
      message.error(err.msg || '添加资产失败');
    }
  };

  // “查看信息”跳转
  const handleViewChart = (symbol, type) => {
    let path = '';
    switch (type) {
      case '股票':
        path = `/stock/kline?symbol=${symbol}`;
        break;
      case '基金':
        path = `/fund/trend?symbol=${symbol}`;
        break;
      case '债券':
        path = `/bond/trend?symbol=${symbol}`;
        break;
      case '外汇':
        path = `/forex/trend?symbol=${symbol}`;
        break;
      default:
        return;
    }
    navigate(path);
  };

  // ─────────────────────────────────────────────────────────────
  // 表格列定义（使用 useMemo 缓存）
  const columns = useMemo(
    () => [
      { title: '产品代码', dataIndex: 'products_id', key: 'products_id', width: 120 },
      { title: '产品名称', dataIndex: 'products_name', key: 'products_name', width: 180 },
      { title: '资产类型', dataIndex: 'type', key: 'type', width: 100 },
      { title: '持仓数量', dataIndex: 'quantity', key: 'quantity', width: 100 },
      {
        title: '买入价格 (¥)',
        dataIndex: 'buy_price',
        key: 'buy_price',
        width: 100,
        render: (v) => Number(v).toFixed(2),
      },
      {
        title: '当前价／净值 (¥)',
        dataIndex: 'currentPrice',
        key: 'currentPrice',
        width: 120,
        render: (v) => (v != null && !isNaN(v) ? Number(v).toFixed(2) : '-'),
      },
      {
        title: '成本市值 (¥)',
        dataIndex: 'costValue',
        key: 'costValue',
        width: 120,
        render: (v) => (v != null && !isNaN(v) ? Number(v).toFixed(2) : '-'),
      },
      {
        title: '当前市值 (¥)',
        dataIndex: 'marketValue',
        key: 'marketValue',
        width: 120,
        render: (v) => (v != null && !isNaN(v) ? Number(v).toFixed(2) : '-'),
      },
      {
        title: '盈亏 (¥)',
        dataIndex: 'profitLoss',
        key: 'profitLoss',
        width: 100,
        render: (v) => {
          if (v == null || isNaN(v)) return '-';
          const val = Number(v).toFixed(2);
          return (
            <span style={{ color: v >= 0 ? '#52c41a' : '#f5222d' }}>
              {v >= 0 ? '+' : ''}
              {val}
            </span>
          );
        },
      },
      {
        title: '盈亏 (%)',
        dataIndex: 'profitPct',
        key: 'profitPct',
        width: 100,
        render: (v) => (v != null && !isNaN(v) ? `${v.toFixed(2)}%` : '-'),
      },
      {
        title: '操作',
        key: 'action',
        width: 160,
        render: (_, record) => (
          <>
            <Button
              type="link"
              onClick={() => handleViewChart(record.products_id, record.type)}
            >
              查看信息
            </Button>
            <Button
              type="link"
              danger
              onClick={() => handleDeleteAsset(record.id)}
            >
              删除
            </Button>
          </>
        ),
      },
    ],
    []
  );

  // ─────────────────────────────────────────────────────────────
  return (
    <div className="user-asset-page">
      <h1>用户资产管理（含股票/基金/债券/外汇实时对比）</h1>

      {/* “手动添加资产”按钮 */}
      <Button
        type="primary"
        onClick={() => setIsModalOpen(true)}
        style={{ marginBottom: 16 }}
      >
        手动添加资产
      </Button>

      {/* 添加资产弹窗 */}
      <Modal
        title="手动添加资产"
        open={isModalOpen}
        onCancel={() => setIsModalOpen(false)}
        footer={null}
      >
        <Form onFinish={handleAddAsset} layout="vertical">
          <Form.Item
            label="产品代码"
            name="products_id"
            rules={[{ required: true, message: '请输入产品代码' }]}
          >
            <Input placeholder="例如：600519.SH / 014938 / sh110059 / USDZAR" />
          </Form.Item>
          <Form.Item
            label="产品名称"
            name="products_name"
            rules={[{ required: true, message: '请输入产品名称' }]}
          >
            <Input />
          </Form.Item>
          <Form.Item
            label="资产类型"
            name="type"
            rules={[{ required: true, message: '请选择资产类型' }]}
          >
            <Select placeholder="请选择资产类型">
              <Option value="股票">股票</Option>
              <Option value="基金">基金</Option>
              <Option value="债券">债券</Option>
              <Option value="外汇">外汇</Option>
            </Select>
          </Form.Item>
          <Form.Item
            label="持仓数量"
            name="quantity"
            rules={[{ required: true, message: '请输入持仓数量' }]}
          >
            <InputNumber min={1} style={{ width: '100%' }} />
          </Form.Item>
          <Form.Item
            label="买入价格"
            name="buy_price"
            rules={[{ required: true, message: '请输入买入价格' }]}
          >
            <InputNumber min={0.01} step={0.01} style={{ width: '100%' }} />
          </Form.Item>
          <Form.Item
            label="购入时间"
            name="buy_time"
            rules={[{ required: true, message: '请选择购入时间' }]}
          >
            <DatePicker showTime style={{ width: '100%' }} />
          </Form.Item>
          <Form.Item>
            <Button type="primary" htmlType="submit" block>
              确认添加
            </Button>
          </Form.Item>
        </Form>
      </Modal>

      {loading ? (
        <div className="spin-center">
          <Spin />
        </div>
      ) : (
        <>
          {/* 饼图：所有资产市值占比 */}
          <Card
            className="user-asset-page__chart-card"
            bordered={false}
            style={{ marginBottom: 24 }}
          >
            <div
              ref={pieAllRef}
              className="user-asset-page__pie-chart"
            />
            {computedAssets.length === 0 ||
            Object.values(
              computedAssets.reduce((acc, it) => {
                acc[it.type] = (acc[it.type] || 0) + Number(it.marketValue || 0);
                return acc;
              }, {})
            ).every((v) => v === 0) ? (
              <Text
                type="warning"
                style={{ display: 'block', textAlign: 'center', marginTop: 8 }}
              >
                当前无资产，请添加资产
              </Text>
            ) : null}
          </Card>

          {/* 饼图：股票持仓市值占比 */}
          <Card
            className="user-asset-page__chart-card"
            bordered={false}
            style={{ marginBottom: 24 }}
          >
            <div
              ref={pieStockRef}
              className="user-asset-page__pie-chart"
            />
            {computedAssets.filter(
              (it) => it.type === '股票' && Number(it.marketValue || 0) > 0
            ).length === 0 ? (
              <Text
                type="warning"
                style={{ display: 'block', textAlign: 'center', marginTop: 8 }}
              >
                当前无股票持仓
              </Text>
            ) : null}
          </Card>

          {/* 条形图：股票持仓盈亏 */}
          <Card
            className="user-asset-page__chart-card"
            bordered={false}
            style={{ marginBottom: 24 }}
          >
            <div
              ref={barRef}
              className="user-asset-page__bar-chart"
            />
            {computedAssets.filter(
              (it) =>
                it.type === '股票' &&
                it.profitLoss != null &&
                !isNaN(Number(it.profitLoss))
            ).length === 0 ? (
              <Text
                type="warning"
                style={{ display: 'block', textAlign: 'center', marginTop: 8 }}
              >
                当前无股票
              </Text>
            ) : null}
          </Card>

          {/* 资产列表 */}
          <Table
            rowKey="id"
            dataSource={computedAssets}
            columns={columns}
            pagination={{ pageSize: 10 }}
            scroll={{ x: 'max-content', y: 400 }}
          />
        </>
      )}
    </div>
  );
};

export default UserAsset;
